package cn.iocoder.yudao.module.design.controller.admin.problem;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.design.controller.admin.problem.vo.*;
import cn.iocoder.yudao.module.design.controller.admin.problemdealerrel.vo.ProblemDealerRelStatusUpdateReqVO;
import cn.iocoder.yudao.module.design.controller.admin.probleminnerrel.vo.ProblemInnerRelCreateReqVO;
import cn.iocoder.yudao.module.design.convert.problem.ProblemConvert;
import cn.iocoder.yudao.module.design.dal.dataobject.pic.PicDO;
import cn.iocoder.yudao.module.design.dal.dataobject.problem.ProblemDO;
import cn.iocoder.yudao.module.design.dal.dataobject.problemdealerrel.ProblemDealerRelDO;
import cn.iocoder.yudao.module.design.enums.design.PicUploadTypeEnum;
import cn.iocoder.yudao.module.design.service.flowtask.FlowTaskService;
import cn.iocoder.yudao.module.design.service.node.NodeService;
import cn.iocoder.yudao.module.design.service.pic.PicService;
import cn.iocoder.yudao.module.design.service.problem.ProblemService;
import cn.iocoder.yudao.module.design.service.problemdealerrel.ProblemDealerRelService;
import cn.iocoder.yudao.module.design.service.probleminnerrel.ProblemInnerRelService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.module.design.enums.design.PicSourceTypeEnum.PIC_SOURCE_TYPE_ENUM_005;

@Tag(name = "管理后台 - 项目问题")
@RestController
@RequestMapping("/design/problem")
@Validated
public class ProblemController {

    @Resource
    private ProblemService problemService;
    @Resource
    private PicService picService;
    @Resource
    private FlowTaskService flowTaskService;
    @Resource
    private ProblemInnerRelService problemInnerRelService;

    @Resource
    private ProblemDealerRelService problemDealerRelService;

    @Resource
    private NodeService nodeService;

    @PostMapping("/create")
    @Operation(summary ="创建项目问题")
    @PreAuthorize("@ss.hasPermission('design:problem:create')")
    public CommonResult<Long> createProblem(@Valid @RequestBody ProblemCreateReqVO createReqVO) {

        Long problemId = problemService.createProblem(createReqVO);
        // 保存图片资源
        PicDO picDo = new PicDO();
        picDo.setHouseId(createReqVO.getHouseId());
        picDo.setFlowId(createReqVO.getFlowId());
        picDo.setNodeId(createReqVO.getNodeId());
        picDo.setItemId(problemId);
        picDo.setUploadType(PicUploadTypeEnum.PIC_UPLOAD_TYPE_ENUM_0.getCode());
        picDo.setSourceType(PIC_SOURCE_TYPE_ENUM_005.getCode());
        picService.savePicData(picDo, createReqVO.getFileList());

        // 判断是否有关联问题 （默认新建问题为前置问题 problemid 完成后开启 relProblemId）
        Long relProblemId = createReqVO.getRelProblemId();
        if (relProblemId != null) {
            ProblemInnerRelCreateReqVO problemInnerRelCreateReqVO = new ProblemInnerRelCreateReqVO();
            problemInnerRelCreateReqVO.setHouseId(createReqVO.getHouseId());
            problemInnerRelCreateReqVO.setFlowId(createReqVO.getFlowId());
            problemInnerRelCreateReqVO.setNodeId(createReqVO.getNodeId());
            // 新建问题id
            problemInnerRelCreateReqVO.setProblemId(problemId);
            // 关联问题
            problemInnerRelCreateReqVO.setRelProblemId(relProblemId);
            // 关联类型 默认是0 前置问题  problemId 是 relProblemId 的 前置问题
            problemInnerRelCreateReqVO.setDependType("0");
            // 建立关联关系
            problemInnerRelService.createProblemInnerRel(problemInnerRelCreateReqVO);
        }

        return success(problemId);
    }

    @PostMapping("/createDealerIds")
    @Operation(summary ="创建项目问题")
    @PreAuthorize("@ss.hasPermission('design:problem:create')")
    public CommonResult<Long> createProblemDealerIds(@Valid @RequestBody ProblemCreateReqVO createReqVO) {

        Long problemId = problemService.createProblem(createReqVO);
        // 保存图片资源
        PicDO picDo = new PicDO();
        picDo.setHouseId(createReqVO.getHouseId());
        picDo.setFlowId(createReqVO.getFlowId());
        picDo.setNodeId(createReqVO.getNodeId());
        picDo.setItemId(problemId);
        picDo.setUploadType(PicUploadTypeEnum.PIC_UPLOAD_TYPE_ENUM_0.getCode());
        picDo.setSourceType(PIC_SOURCE_TYPE_ENUM_005.getCode());
        picService.savePicData(picDo, createReqVO.getFileList());

        /**根据problemId 和DealerIds 内多个id 关联形成一对多  默认状态为待确认   发送待办*/
        // 保存 problem 和每个处理人的关系
        if(CollUtil.isNotEmpty(createReqVO.getDealerIds())){
            for (Long userId:createReqVO.getDealerIds()) {

                problemDealerRelService.createProblemDealerRel(userId,problemId);
            }
        }
        return success(problemId);
    }

    @PutMapping("/update")
    @Operation(summary ="更新项目问题")
    @PreAuthorize("@ss.hasPermission('design:problem:update')")
    public CommonResult<Boolean> updateProblem(@Valid @RequestBody ProblemUpdateReqVO updateReqVO) {
        problemService.updateProblem(updateReqVO);
        // 保存图片文件
        PicDO picDo = new PicDO();
        picDo.setHouseId(updateReqVO.getHouseId());
        picDo.setFlowId(updateReqVO.getFlowId());
        picDo.setNodeId(updateReqVO.getNodeId());
        picDo.setItemId(updateReqVO.getId());
        picDo.setUploadType(PicUploadTypeEnum.PIC_UPLOAD_TYPE_ENUM_0.getCode());
        picDo.setSourceType(PIC_SOURCE_TYPE_ENUM_005.getCode());
        picService.savePicData(picDo, updateReqVO.getFileList());

       // 查询存量处理人id
        List<ProblemDealerRelDO> exitsUserId = problemDealerRelService.getProblemDealerRelListByProblemId(updateReqVO.getId());
        Set<Long> exitsUserIds = exitsUserId.stream()   // 将列表转换为流
                .map(ProblemDealerRelDO::getUserId)  // 使用 map 方法获取每个用户的 userId
                .collect(Collectors.toSet()); // 将结果收集到另一个列表中
        // 存量处理人id 与传入的处理人id 进行比较
        List<List<Long>> lists = CollectionUtils.diffList(exitsUserIds, updateReqVO.getDealerIds(), (oldVal, newVal) -> {
            boolean same = ObjectUtil.equal(oldVal, newVal);
            if (same) {
                newVal = oldVal;
            }
            return same;
        });
        Long problemId = updateReqVO.getId();
        // 保存 problem 和每个处理人的关系   （新增人员）
        if(CollUtil.isNotEmpty(lists.get(0))){
            for (Long userId:lists.get(0)) {

                problemDealerRelService.createProblemDealerRel(userId,problemId);
            }
        }
        // 保存 problem 和每个处理人的关系   （删除人员）
        if(CollUtil.isNotEmpty(lists.get(2))){
            for (Long userId:lists.get(2)) {
                problemDealerRelService.deleteProblemDealerRel(userId,problemId);
            }
        }
        // 记录每次变更记录


        return success(true);
    }

    @PutMapping("/updateProblemStatus")
    @Operation(summary ="更新项目问题状态")
    @PreAuthorize("@ss.hasPermission('design:problem:update')")
    public CommonResult<Boolean> updateProblemStatus(@Valid @RequestBody ProblemUpdateReqVO updateReqVO) {
        /**
         *  1.判断问题id 是否存在
         *  2.如果修改为关闭 则判断是否有后置任务  有则关闭当前问题  开启后置问题 x
         *  3.通知后置任务处理人开启问题  x
         *  4.考虑 2 一个问题 有多个前置问题 情况 做以下处理
         *      · 查询出来 关闭问题的 所有后续任务
         *      · 判断所有后续任务 的前置任务 是否都完成
         *      ·   都完成了 则开启这个后置任务
         *      ·   未完成   则通知前置任务已完成  还有几个前置任务未完成 请关注
         *
         */
        if ("2".equals(updateReqVO.getStatus())) {
            updateReqVO.setFinishTime(new Date());
        }
        problemService.updateProblemStatus(updateReqVO);

        // 判断是否将问题 改为关闭状态
        if ("2".equals(updateReqVO.getStatus())) {
            problemService.dealProblemNotifyWorker(updateReqVO.getId());
        }
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary ="删除项目问题")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('design:problem:delete')")
    public CommonResult<Boolean> deleteProblem(@RequestParam("id") Long id) {
        problemService.deleteProblem(id);
        return success(true);
    }


    @GetMapping("/getProblemData")
    @Operation(summary ="获得项目问题详情")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('design:problem:query')")
    public CommonResult<ProblemRespDetailVO> getProblemData(@RequestParam("id") Long id) {
        ProblemRespDetailVO problemData = problemService.getProblemData(id);
        Map<String, Object> nodeInfo = nodeService.getNodeInfoById(problemData.getNodeId());
        problemData.setNodeInfo(nodeInfo);
        // 查询 图片数据
        // 查询上传附件,图片1
        PicDO picDO = new PicDO();
        picDO.setHouseId(problemData.getHouseId());
        picDO.setFlowId(problemData.getFlowId());
        picDO.setNodeId(problemData.getNodeId());
        picDO.setItemId(problemData.getId());
        picDO.setUploadType(PicUploadTypeEnum.PIC_UPLOAD_TYPE_ENUM_0.getCode());
        picDO.setSourceType(PIC_SOURCE_TYPE_ENUM_005.getCode());
        List<PicDO> picData = picService.getPicData(picDO);
        problemData.setFileList(picData);

       Set problemIds = new HashSet<>();
        problemIds.add(problemData.getId());
        // 查询problemId 对应的关联人
         List<ProblemDealerRelDO> problemDealerRelDOs = problemDealerRelService.getProblemDealerRelListByProblemIds(problemIds);
        if(CollUtil.isNotEmpty(problemDealerRelDOs)){
            List<Long> userIds = problemDealerRelDOs.stream()   // 将列表转换为流
                    .map(ProblemDealerRelDO::getUserId)  // 使用 map 方法获取每个用户的 userId
                    .collect(Collectors.toList()); // 将结果收集到另一个列表中
            problemData.setDealerIds(userIds);
            problemData.setDealerList(problemDealerRelDOs);
        }
        return success(problemData);
    }


    @GetMapping("/get")
    @Operation(summary ="获得项目问题")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('design:problem:query')")
    public CommonResult<ProblemRespVO> getProblem(@RequestParam("id") Long id) {
        ProblemDO problem = problemService.getProblem(id);
        return success(ProblemConvert.INSTANCE.convert(problem));
    }

    @GetMapping("/list")
    @Operation(summary ="获得项目问题列表")
    @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
    @PreAuthorize("@ss.hasPermission('design:problem:query')")
    public CommonResult<List<ProblemRespVO>> getProblemList(@RequestParam("ids") Collection<Long> ids) {
        List<ProblemDO> list = problemService.getProblemList(ids);
        return success(ProblemConvert.INSTANCE.convertList(list));
    }

    @GetMapping("/page")
    @Operation(summary ="获得项目问题分页")
    @PreAuthorize("@ss.hasPermission('design:problem:query')")
    public CommonResult<PageResult<ProblemRespVO>> getProblemPage(@Valid ProblemPageReqVO pageVO) {
        Set<Long> ids = new HashSet<>();
        List<ProblemDealerRelDO>  dealerRels = new ArrayList<>();
//        if(!ObjectUtil.isEmpty(pageVO.getUserId())){
//             dealerRels = problemDealerRelService.getProblemDealerRelListByUserId(pageVO.getUserId());
//
//
//        }
        if(!ObjectUtil.isEmpty(pageVO.getDealerId())){
            dealerRels = problemDealerRelService.getProblemDealerRelListByUserId(pageVO.getDealerId());

        }
        if(dealerRels.size()>0){
            ids = dealerRels.stream()   // 将列表转换为流
                    .map(ProblemDealerRelDO::getProblemId)  // 使用 map 方法获取每个用户的 userId
                    .collect(Collectors.toSet()); // 将结果收集到另一个列表中
            pageVO.setIds(ids);
            pageVO.setDealerId(null);
        }
        PageResult<ProblemDO> pageResult = problemService.getProblemPage(pageVO);
        // 项目id集合
        Set<Long> houseIdList = new HashSet<>(convertList(pageResult.getList(), ProblemDO::getId));

        // 查询problemId 对应的关联人
        Map<Long, List<ProblemDealerRelDO>> problemDealerMap = problemDealerRelService.getProblemDealerRelListMap(houseIdList);
        // 拼接结果返回
        List<ProblemRespVO> preblemRespVOList = new ArrayList<>(pageResult.getList().size());
        pageResult.getList().forEach(problemDO -> {
            ProblemRespVO respVO = ProblemConvert.INSTANCE.convert(problemDO);
            List<ProblemDealerRelDO> problemDealerRelDOs = problemDealerMap.get(problemDO.getId());
            if(CollUtil.isNotEmpty(problemDealerRelDOs)){
                List<Long> userIds = problemDealerRelDOs.stream()   // 将列表转换为流
                        .map(ProblemDealerRelDO::getUserId)  // 使用 map 方法获取每个用户的 userId
                        .collect(Collectors.toList()); // 将结果收集到另一个列表中
                respVO.setDealerIds(userIds);
            }
            preblemRespVOList.add(respVO);

        });
        return success(new PageResult<>(preblemRespVOList, pageResult.getTotal()));
    }

    @GetMapping("/export-excel")
    @Operation(summary ="导出项目问题 Excel")
    @PreAuthorize("@ss.hasPermission('design:problem:export')")
   
    public void exportProblemExcel(@Valid ProblemExportReqVO exportReqVO,
                                   HttpServletResponse response) throws IOException {
        List<ProblemDO> list = problemService.getProblemList(exportReqVO);
        // 导出 Excel
        List<ProblemExcelVO> datas = ProblemConvert.INSTANCE.convertList02(list);
        ExcelUtils.write(response, "项目问题.xls", "数据", ProblemExcelVO.class, datas);
    }

    @PostMapping("/getProblemSimInfo")
    @Operation(summary ="获取项目问题简要信息")
    @PreAuthorize("@ss.hasPermission('design:problem:query')")
    public CommonResult<List<ProblemSimResVO>> getProblemSimInfo(@Valid @RequestBody ProblemSimReqVO context) {
        return success(ProblemConvert.INSTANCE.convertSimList(problemService.getProblemSimInfo(context)));
    }

    @PostMapping("/getPreProblemSimList")
    @Operation(summary ="获取依赖前置问题列表")
    @PreAuthorize("@ss.hasPermission('design:problem:query')")
    public CommonResult<List<ProblemSimResVO>> getPreProblemSimList(@Valid @RequestBody ProblemSimReqVO context) {
        return success(ProblemConvert.INSTANCE.convertSimList(problemService.getPreProblemSimList(context)));
    }

    @PostMapping("/addRelProblem")
    @Operation(summary ="关联问题")
    @PreAuthorize("@ss.hasPermission('design:problem:create')")
    public CommonResult<Long > addRelProblem(@Valid @RequestBody ProblemRelReqVO context) {
        ProblemDO problem = problemService.getProblem(context.getProblemId());

        ProblemInnerRelCreateReqVO createReqVO = new ProblemInnerRelCreateReqVO();
        createReqVO.setHouseId(problem.getHouseId());
        createReqVO.setFlowId(problem.getFlowId());
        createReqVO.setNodeId(problem.getNodeId());
        createReqVO.setProblemId(problem.getId());
        createReqVO.setRelProblemId(context.getRelProblemId());
        Long problemInnerRel = problemInnerRelService.createProblemInnerRel(createReqVO);
        return success( problemInnerRel);
    }


    @PutMapping("/updateProblemDealerStatus")
    @Operation(summary ="更新项目问题处理状态")
    @PreAuthorize("@ss.hasPermission('design:problem:update')")
    public CommonResult<Boolean> updateProblemDealerStatus(@Valid @RequestBody ProblemDealerRelStatusUpdateReqVO updateReqVO) {

        if(ObjectUtil.isEmpty(updateReqVO.getUserId())){
            updateReqVO.setUserId(SecurityFrameworkUtils.getLoginUserId());
        }
        problemDealerRelService.updateProblemDealerRelStatus(updateReqVO.getProblemId(),updateReqVO.getUserId(),updateReqVO.getStatusCd());

        return success(true);
    }

}
